package cn.maihe.elg.operation.centers.hymake.handler.service;

import cn.maihe.elg.operation.centers.hymake.config.HyMakeInfoConfig;
import cn.maihe.elg.operation.centers.hymake.dto.HyMakeBaseRespDTO;
import cn.maihe.elg.operation.centers.hymake.dto.handler.LstApplyReqDTO;
import cn.maihe.elg.operation.centers.hymake.dto.handler.LstApplyRespDTO;
import cn.maihe.elg.operation.centers.hymake.dto.handler.vo.TbInsuranceSchema;
import cn.maihe.elg.operation.centers.hymake.dto.handler.vo.TbMainLiab;
import cn.maihe.elg.operation.centers.hymake.dto.handler.vo.TbPolicyDto;
import cn.maihe.elg.operation.centers.hymake.dto.handler.vo.TbProvinceSupply;
import cn.maihe.elg.operation.centers.hymake.enums.HyMakeRespCodeEnum;
import cn.maihe.elg.operation.centers.hymake.handler.HyMakeCenterTradeService;
import cn.maihe.elg.operation.centers.supports.CenterTradeContext;
import cn.maihe.elg.operation.centers.supports.annotation.CenterTradeService;
import cn.maihe.elg.operation.model.bo.AcceptOrderBO;
import cn.maihe.elg.operation.model.bo.ApplyTemplatePdfParams;
import cn.maihe.elg.operation.model.enums.AcceptOrderStatus;
import cn.maihe.elg.operation.model.enums.AttachmentFileType;
import cn.maihe.elg.operation.model.enums.BidCustomerStatus;
import cn.maihe.elg.operation.model.enums.CenterNoEnum;
import cn.maihe.elg.operation.model.enums.CenterProviderEnum;
import cn.maihe.elg.operation.model.enums.CertifyCodeEnum;
import cn.maihe.elg.operation.model.enums.GuaranteeCategory;
import cn.maihe.elg.operation.model.enums.GuaranteeType;
import cn.maihe.elg.operation.model.enums.IDType;
import cn.maihe.elg.operation.model.enums.InstitutionOrgCodeEnum;
import cn.maihe.elg.operation.model.enums.TradeType;
import cn.maihe.elg.operation.model.enums.UserStatusEnum;
import cn.maihe.elg.operation.model.enums.UserType;
import cn.maihe.elg.operation.repository.entity.AcceptOrderInfoDO;
import cn.maihe.elg.operation.repository.entity.BidCustomerDO;
import cn.maihe.elg.operation.repository.entity.GuaranteeInstitutionDO;
import cn.maihe.elg.operation.repository.entity.ProjectInfoDO;
import cn.maihe.elg.operation.repository.entity.UserDO;
import cn.maihe.elg.operation.service.business.BidCustomerService;
import cn.maihe.elg.operation.service.business.ProjectInfoService;
import cn.maihe.elg.operation.service.order.AcceptContentService;
import cn.maihe.elg.operation.service.order.AcceptOrderInfoService;
import cn.maihe.elg.operation.service.order.GuaranteeAttachmentInfoService;
import cn.maihe.elg.operation.supports.system.ElgResourceService;
import cn.maihe.elg.operation.utils.AutoDiscernTemplateUtil;
import cn.maihe.elg.operation.utils.DateUtil;
import cn.maihe.elg.operation.utils.IdGenerate;
import cn.maihe.elg.operation.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Triple;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Instant;
import java.util.Date;

/**
 * @Description 4.1.1承保接口
 * 接口功能描述
 * 电子保函平台向出函机构（保险公司/银行）推送承保信息，
 * 保函保费由出函机构计算后返回。
 * @Author WJH
 * @Date 2022/03/31
 */
@CenterTradeService(
        provider = CenterProviderEnum.HYMAKE,
        centerNo = CenterNoEnum.NINGDE,
        tradeType = TradeType.lstApply,
        reqClass = LstApplyReqDTO.class,
        respClass = LstApplyRespDTO.class
)
@Slf4j
public class HyMakeLstApplyService extends HyMakeCenterTradeService<LstApplyReqDTO, LstApplyRespDTO> {
    public HyMakeLstApplyService(HyMakeInfoConfig centerInfosConfig) {
        super(centerInfosConfig);
    }

    @Resource
    private AcceptOrderInfoService acceptOrderInfoService;
    @Resource
    private ElgResourceService elgResourceService;
    @Resource
    private GuaranteeAttachmentInfoService guaranteeAttachmentInfoService;
    @Resource
    private ProjectInfoService projectInfoService;
    @Resource
    private AcceptContentService acceptContentService;
    @Resource
    private BidCustomerService bidCustomerService;

    @Override
    protected void verifyParam(CenterTradeContext<LstApplyReqDTO, LstApplyRespDTO> context) {
        super.verifyParam(context);
        LstApplyReqDTO req = context.getReq();
        TbPolicyDto policyDto = req.getTbPolicyDtoList().get(0);
        String centerOrderId = policyDto.getBusinessNo();
        boolean exists = acceptOrderInfoService.existsCenterOrderId(context.getCenterId(), centerOrderId);
        Assert.isTrue(!exists, () -> "保单流水号已存在");
    }

    @Override
    public LstApplyRespDTO processService(CenterTradeContext<LstApplyReqDTO, LstApplyRespDTO> context) {

        AcceptOrderBO acceptOrderBO = this.parseApplyGuaranteeInfo(context);

        LstApplyRespDTO resp = new LstApplyRespDTO();

        try {
            bidCustomerService.checkBidderContractInfo(acceptOrderBO.getBidCustomer());
        } catch (Exception e) {
            resp.setCode(HyMakeRespCodeEnum.FAILURE.getRespCode());
            resp.setMessage(e.getMessage());
            return resp;
        }

        acceptOrderBO = acceptOrderInfoService.saveAcceptOrderBO(acceptOrderBO);

        resp = buildResp(acceptOrderBO);

        acceptContentService.saveOrUpdateAcceptContent(acceptOrderBO.getAcceptOrderInfo().getAcceptOrderNo(), context.getReq());

        return resp;
    }

    private LstApplyRespDTO buildResp(AcceptOrderBO acceptOrderBO) {
        LstApplyRespDTO resp = HyMakeBaseRespDTO.success("承保完成", LstApplyRespDTO.class);
        //投标企业是否已提交企业认证资料且已审核通过
        BidCustomerDO bidCustomerDO = acceptOrderBO.getBidCustomer();

        LstApplyRespDTO.BizData data = new LstApplyRespDTO.BizData();
        AcceptOrderInfoDO acceptOrderInfo = acceptOrderBO.getAcceptOrderInfo();
        // 承保接口同步返回信息，等待中心投保材料地址推送后，中心获取支付链接时得兴才有介入审核
        data.setInsuranceNo(acceptOrderInfo.getAcceptOrderNo());
        data.setPremium(StringUtil.toYuan(acceptOrderInfo.getGuaranteeFee()));
        //费率单位
        data.setRate(StringUtil.multiplyTen(acceptOrderInfo.getFeeRate(), 2));
        //跳转到该订单上传申请书&反担保协议书 及 支付凭证页面
//        makeAndSaveApplyFile(acceptOrderBO);
        resp.setData(data);
        return resp;
    }

    /**
     * docx模板合成申请书
     */
    private void makeAndSaveApplyFile(AcceptOrderBO acceptOrderBO) {
        ApplyTemplatePdfParams params = new ApplyTemplatePdfParams();
        params.setBidderName(acceptOrderBO.getBidCustomer().getBidderName());
        params.setProjectName(acceptOrderBO.getProjectInfo().getProjectName());
        Triple<String, String, String> triple = DateUtil.parseLocalDate();
        params.setYear(triple.getLeft());
        params.setMonth(triple.getMiddle());
        params.setDay(triple.getRight());
        AcceptOrderInfoDO orderInfo = acceptOrderBO.getAcceptOrderInfo();
        String acceptOrderNo = orderInfo.getAcceptOrderNo();
        Path docxPath = elgResourceService.buildApplyFileByTemplate(acceptOrderNo, params);

        guaranteeAttachmentInfoService.saveOrUpdateAttachmentInfo(orderInfo, docxPath, AttachmentFileType.TYPE_12, "申请书未签章");

    }


    /**
     * 解析 受理的清单信息
     */
    private AcceptOrderBO parseApplyGuaranteeInfo(CenterTradeContext<LstApplyReqDTO, LstApplyRespDTO> context) {
        LstApplyReqDTO req = context.getReq();
        long centerId = context.getCenterId();
        long orgId = context.getOrgId();
        //固定得兴担保直开式
        InstitutionOrgCodeEnum institutionOrgCodeEnum = InstitutionOrgCodeEnum.resolve(context.getOrgCode());
//        InstitutionCode curInstitutionCode = InstitutionCode.deXing;
        GuaranteeInstitutionDO institutionDO = getInstitutionIdByCode(institutionOrgCodeEnum);
        String acceptOrderNo = IdGenerate.genAcceptOrderNo(context.getCenterNoEnum());

        ProjectInfoDO projectInfoDO = this.buildProjectInfo(context.getCenterNoEnum(),req, centerId, orgId);
        BidCustomerDO bidCustomerDO = this.buildBidCustomerInfo(req, centerId, orgId);
        UserDO userDO = this.buildUserInfo(req, centerId, orgId);
        AcceptOrderInfoDO acceptOrderInfoDO = this.buildAcceptOrderInfo(acceptOrderNo, req, centerId, orgId, institutionDO);
        //计算保费
        CertifyCodeEnum certifyCode = CertifyCodeEnum.resolve(acceptOrderInfoDO.getCertifyCode());
        if (certifyCode.equals(CertifyCodeEnum.HYMMZ)) {
            acceptOrderInfoDO.setGuaranteeFee(getYouXiMZGuaranteeFee(projectInfoDO.getBidBond()));
        } else {
            String feeRate = this.getCurCenterInfo(context).getFeeRate();
            acceptOrderInfoDO.setFeeRate(feeRate);
            Long minFeeYuan = this.getCurCenterInfo(context).getMinFeeYuan();
            Long maxFeeYuan = this.getCurCenterInfo(context).getMaxFeeYuan();
            acceptOrderInfoDO.setGuaranteeFee(this.calcGuaranteeFee(projectInfoDO.getBidBond(), feeRate, minFeeYuan,maxFeeYuan));
        }
        AcceptOrderBO orderBO = AcceptOrderBO.builder().centerId(centerId).orgId(orgId)
                .acceptOrderInfo(acceptOrderInfoDO).projectInfo(projectInfoDO).bidCustomer(bidCustomerDO).userDO(userDO).build();

        //默认投标保函类别;
        orderBO.setGuaranteeCategory(GuaranteeCategory.BID);
        //默认担保公司担保类型;
        orderBO.setGuaranteeType(GuaranteeType.GUARANTEE);

        orderBO.setInstitutionOrgCodeEnum(institutionOrgCodeEnum);
        orderBO.setIsInnerApply(false);

        //出函机构赋值
        acceptOrderInfoDO.setInstitutionId(institutionDO.getId());
        acceptOrderInfoDO.setGuaranteeType(orderBO.getGuaranteeType().getTypeStr());
        acceptOrderInfoDO.setGuaranteeCategory(orderBO.getGuaranteeCategory().getCategoryStr());


        return orderBO;
    }


    private AcceptOrderInfoDO buildAcceptOrderInfo(String acceptOrderNo, LstApplyReqDTO req, long centerId, long orgId, GuaranteeInstitutionDO institutionDO) {
        TbPolicyDto data = req.getTbPolicyDtoList().get(0);
        TbInsuranceSchema insuranceSchema = data.getTbInsuranceSchema();
        TbMainLiab mainLiab = data.getTbMainLiab();
        TbProvinceSupply provinceSupply = data.getTbProvinceSupply();
        String projectCode = mainLiab.getInsureArea();
        String projectName = mainLiab.getBusinessDetail();

        return AcceptOrderInfoDO.builder()
                .centerId(centerId).orgId(orgId)
                .guaranteeNo(IdGenerate.genGuaranteeNo(institutionDO.getInstitutionCode()))
                .centerOrderId(data.getBusinessNo())
                .centerOrderTime(DateUtil.getDatetime())
                .acceptOrderNo(acceptOrderNo)
                .inviteCode(insuranceSchema.getAgentCode())
                .projectName(projectName)
                .sectionName(provinceSupply.getSectionName())
                .bidCustomerName(insuranceSchema.getHolderName())
                //当前投标期限保证金截止时间
                .bidIndate(DateUtil.parseDate(mainLiab.getLiabreportstartdate(), "yyyy-MM-dd HH:mm:ss"))
                .guaranteeType(null)//'保函类型'
                .guaranteeCategory(null) //'保函品种'
                .templateId(null)//'报价模板主键id'
                .feeRate(null)
                .guaranteeFee(null)//'保费金额分'
                .status(AcceptOrderStatus.WAIT_SUBMIT_FIRST_TRAIL.getStatus())
                .guaranteeTime(null)
                .projectId(null)//  '投保项目主键id' 关联保存时统一设置
                .bidCustomerId(null)// '投保客户主键id'
                .institutionId(null) //'开函机构主键'
                .attachmentId(null)//
                .applyOrderNo(null)
                .invoiceFlag(null)
                .invoiceId(null)
                .warnFlag(0).warnContent(null)
                .gmtCreate(Date.from(Instant.now()))
                .certifyCode(insuranceSchema.getCertifyCode())
                .build();
    }

    private BidCustomerDO buildBidCustomerInfo(LstApplyReqDTO req, long centerId, long orgId) {
        // 其他信息通过 企业认证补充页面收集
        TbPolicyDto data = req.getTbPolicyDtoList().get(0);
        TbInsuranceSchema insuranceSchema = data.getTbInsuranceSchema();
        TbMainLiab mainLiab = data.getTbMainLiab();
        TbProvinceSupply provinceSupply = data.getTbProvinceSupply();

        BidCustomerDO bidCustomer = new BidCustomerDO();
        bidCustomer.setCenterId(centerId);
        bidCustomer.setOrgId(orgId);
        bidCustomer.setBidderName(insuranceSchema.getHolderName());
        bidCustomer.setBidderCreditCode(insuranceSchema.getHolderIdNo());
        bidCustomer.setBidderContactName(insuranceSchema.getFrameNo());
        bidCustomer.setBidderContactTel(insuranceSchema.getHolderMobile());
        bidCustomer.setBidderContactIdcard(insuranceSchema.getBidderContactIdCard());
        bidCustomer.setBidderContactIdcardType(IDType.ID_CARD.getType());
        bidCustomer.setBidderEamil(insuranceSchema.getBidderEmail());
        bidCustomer.setBidderAddress(insuranceSchema.getHolderAddress());
        bidCustomer.setBidderRegAddress(insuranceSchema.getHolderAddress());
        bidCustomer.setLegalPersonName(insuranceSchema.getLegalPersonName());
        bidCustomer.setLegalPersonIdcard(insuranceSchema.getLegalPersonIdcard());
        bidCustomer.setLegalPersonIdcardType(IDType.ID_CARD.getType());
        bidCustomer.setLegalPersonTel(insuranceSchema.getLegalPersonTel());
        bidCustomer.setEnableAutoApprove(0);
        bidCustomer.setBlacklistFlag(0);
        bidCustomer.setBidderCapital(null);
        bidCustomer.setBidderLegal(insuranceSchema.getLegalPersonName());
        bidCustomer.setBidderBeginDate(null);
        bidCustomer.setBidderEndDate(null);
        bidCustomer.setBidderWebsite(null);
        bidCustomer.setBidderIpcNo(null);
        bidCustomer.setLegalBeginDate(null);
        bidCustomer.setLegalEndDate(null);
        bidCustomer.setLicenseName(insuranceSchema.getBidderAccountName());
        bidCustomer.setLicenseAccount(insuranceSchema.getBidderAccountNo());
        bidCustomer.setLicenseLegal(insuranceSchema.getLegalPersonName());
        bidCustomer.setLicenseBank(insuranceSchema.getBidderOpenBank());
        bidCustomer.setLicenseCheckNo(null);
        bidCustomer.setLicenseNo(null);
        bidCustomer.setStatus(BidCustomerStatus.NORMAL.getStatus());
        bidCustomer.setAuditDesc(null);
        bidCustomer.setFollowId(null);
        bidCustomer.setBeiandiquCode(null);
        bidCustomer.setBankName(insuranceSchema.getBidderOpenBank());
        bidCustomer.setBankCardNum(insuranceSchema.getBidderAccountNo());
        bidCustomer.setBankUserName(insuranceSchema.getBidderAccountName());
        bidCustomer.setComTelArea(insuranceSchema.getHolderAddress());
        bidCustomer.setComTelNum(insuranceSchema.getHolderMobile());
        bidCustomer.setProvince(null);
        bidCustomer.setCity(null);
        bidCustomer.setDistrict(null);
        bidCustomer.setEnterpriseId(null);
        bidCustomer.setResultQueryTimes(null);

        return bidCustomer;

    }

    private UserDO buildUserInfo(LstApplyReqDTO req, long centerId, long orgId) {
        TbPolicyDto data = req.getTbPolicyDtoList().get(0);
        TbInsuranceSchema insuranceSchema = data.getTbInsuranceSchema();
        TbMainLiab mainLiab = data.getTbMainLiab();
        TbProvinceSupply provinceSupply = data.getTbProvinceSupply();
        return UserDO.builder()
                .umLogin("0")
                .followId(insuranceSchema.getHolderIdNo())
                .username(insuranceSchema.getHolderIdNo())
                .mobileNo(insuranceSchema.getHolderMobile())//改成统一社会信用代码登录
                .name(insuranceSchema.getHolderName())
                .type(UserType.BIDDER.getType())
                .status(UserStatusEnum.NORMAL.name())
                .orgCode("-1")
                .gmtCreate(new Date())
                .gmtModified(new Date())
                .build();
    }

    private ProjectInfoDO buildProjectInfo(CenterNoEnum centerNoEnum,LstApplyReqDTO req, long centerId, long orgId) {
        TbPolicyDto data = req.getTbPolicyDtoList().get(0);
        TbInsuranceSchema insuranceSchema = data.getTbInsuranceSchema();
        TbMainLiab mainLiab = data.getTbMainLiab();
        TbProvinceSupply provinceSupply = data.getTbProvinceSupply();

        String projectCode = mainLiab.getInsureArea();
        String projectName = mainLiab.getBusinessDetail();

        return ProjectInfoDO.builder()
                .centerId(centerId).orgId(orgId)
                .projectCode(projectCode).projectName(projectName)
                .sectionCode(provinceSupply.getSectionCode()).sectionName(provinceSupply.getSectionName())
                .contractReckonPrice(yuan2fenLong(mainLiab.getPreTurnOver()))
                .tenderer(insuranceSchema.getInsuredName())
                .tendererAddress(insuranceSchema.getInsuredAddress())
                .tendererCreditCode(insuranceSchema.getInsuredIdNo())
                .tendererBankOpenbank(insuranceSchema.getInsuredBankOpenBank())
                .tendererBankCode(insuranceSchema.getInsuredBankCode())
                .tendererBankAccount(insuranceSchema.getInsuredBankAccount())
                .tendererContact(insuranceSchema.getInsuredgrantCountry())
                .tendererContactTel(insuranceSchema.getInsuredmobile())
                .cityCode(provinceSupply.getCityCode())
                .tenderProjectType(provinceSupply.getTenderProjectType())
                .bidOpenTime(DateUtil.parseDate(mainLiab.getLiabreportstartdate(), "yyyy-MM-dd HH:mm:ss"))//'开标时间'=投标截止日期
                .validPeriod(Integer.valueOf(provinceSupply.getValidPeriod()))//投标有效期（单位：天）
                .bidBond(yuan2fenLong(insuranceSchema.getAmount()))
                .tenderNoticeUrl(provinceSupply.getTenderNoticeUrl())
                .tenderFileUrl(mainLiab.getTenderFileUrl())
                .tenderFileMd5(mainLiab.getTenderFileMD5())//'招标方文件md5校验值'
                .noticePubDate(StringUtils.isNotBlank(mainLiab.getNoticePubDate()) ? DateUtil.parseDate(mainLiab.getNoticePubDate(), "yyyy-MM-dd HH:mm:ss") : null)
                .templateId(AutoDiscernTemplateUtil.getTemplateIdByTenderProjectType(centerNoEnum,provinceSupply.getTenderProjectType()))
                .remark(null)//无
                .warnFlag(0)// '预警标识0正常 1出函机构无法受理该项目',
                .sourceFlag(0)// '信息来源0自动 1手动',
                .gmtCreate(Date.from(Instant.now()))
                .build();
    }

    private String genTenderFileMd5(String sectionCode, String sectionName, Long centerId, Long orgId, String tenderFileUrl) {
        String tenderFileMd5 = null;
        try {
            if (!StringUtils.isEmpty(tenderFileUrl)) {
                ProjectInfoDO projectInfo = projectInfoService.getBySectionCode(sectionCode, sectionName, centerId, orgId);
                if (projectInfo == null || StringUtils.isEmpty(projectInfo.getTenderFileMd5())) {
                    //download file
                    Path tmpPath = elgResourceService.downloadByURL(tenderFileUrl);

                    String relativePath = elgResourceService.transferAndSaveFile(tmpPath, "ofd", "tenderFile", "标段" + sectionCode + "招标文件");
                    Path savePath = elgResourceService.getAbsolutePath(relativePath);
                    tenderFileMd5 = elgResourceService.getFileMD5AsHex(savePath);
                    try {
                        Files.deleteIfExists(tmpPath);
                    } catch (IOException e) {
                        log.error("删除临时招标文件异常：{}", e.getMessage(), e);
                    }
                } else {
                    tenderFileMd5 = projectInfo.getTenderFileMd5();
                }
            }
        } catch (Exception e) {
            log.error("下载招标文件失败：{}", e.getMessage(), e);
        }
        return tenderFileMd5;
    }

    private Long getYouXiMZGuaranteeFee(Long projectAmount) {
        if (projectAmount < 2000000L) {
            return 10000L;
        } else if (projectAmount < 4000000L) {
            return 15000L;
        } else if (projectAmount < 14000000L) {
            return 20000L;
        } else {
            return Math.round(projectAmount * 0.0015);
        }
    }

}

